#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "qqtcore.h"
#include "qqtframe.h"
#include "sfilecopy.h"

MainWindow::MainWindow ( QWidget* parent ) :
    QMainWindow ( parent ),
    ui ( new Ui::MainWindow )
{
    ui->setupUi ( this );
    setMinimumSize ( 1024, 600 );
    ui->lineEdit->installEventFilter ( this );
    connect ( this, SIGNAL ( clickBtn() ),
              this, SLOT ( on_pushButton_clicked() ), Qt::QueuedConnection );
    ui->lineEdit_2->installEventFilter ( this );
    connect ( this, SIGNAL ( clickBtn2() ),
              this, SLOT ( on_pushButton_2_clicked() ), Qt::QueuedConnection );
    ui->listWidget->setFixedWidth ( 200 );
    ui->listWidget->setWindowTitle ( "Sub App List" );
    ui->lineEdit->setText ( "a0-MainApp" );
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    ui->tx1->clear();
    if ( ui->lineEdit->text().isEmpty() )
    {
        ui->tx1->append ( "应用程序名（也是软件英文名，也是工程名，也是生成的目标名）不能为空" );
        return;
    }
    if ( ui->lineEdit->text() == "template" )
    {
        ui->tx1->append ( "应用程序名（也是软件英文名，也是工程名，也是生成的目标名）不能为template" );
        return;
    }

    //目标 软件工程名
    QString className = ui->lineEdit->text();

    //创建目标文件夹目录结构
    ui->tx1->append ( "正在创建目录结构。。。。" );
    QDir root = QDir ( qApp->applicationDirPath() ).relativeFilePath ( QString ( "%1" ).arg ( CONFIG_ROOT ) );

    QString rootPath = root.absolutePath();
    QString tempName = "QQtTemplateApplication";

    QString projDir = "a0-appproject";
    root.mkdir ( projDir );
    root.cd ( projDir );

    root.mkdir ( className );
    root.cd ( className );
    root.mkdir ( "screenshot" );
    root.mkdir ( "licence" );
    root.mkdir ( "test" );
    root.mkdir ( "source" );
    root.mkdir ( QString ( "source/%1" ).arg ( className ) );

    SFileCopy sf;
    //multi-link直接拷贝，App在自己的工程管理里面需要使用自己的。利于+submodule，利于版本管理。
    //加上这个文件夹，利于直接编译过。后续我会+submodule，使用持续更新的multi-link，不会使用这个。
    //Multipel App，App共用multi-link
    ui->tx1->append ( "正在拷贝multi-link文件夹。。。" );
    sf.copyDirectoryFiles ( QString ( "template/%1/multi-link" ).arg ( tempName ),
                            QString ( "%1/%2/multi-link" ).arg ( projDir ).arg ( className ), true );


    //android直接拷贝 后续还有AndroidManifest.xml fixer
    ui->tx1->append ( "正在拷贝android文件夹。。。" );
    sf.copyDirectoryFiles ( QString ( "template/%1/source/%1/android" ).arg ( tempName ),
                            QString ( "%1/%2/source/%2/android" ).arg ( projDir ).arg ( className ), true );

    //AppRoot直接拷贝
    ui->tx1->append ( "正在拷贝AppRoot文件夹。。。" );
    sf.copyDirectoryFiles ( QString ( "template/%1/source/%1/AppRoot" ).arg ( tempName ),
                            QString ( "%1/%2/source/%2/AppRoot" ).arg ( projDir ).arg ( className ), true );

    //main*直接拷贝 后续还有mainwindow.ui fixer
    //可替代
    ui->tx1->append ( "正在拷贝main文件。。。" );
    sf.copyFileToPath ( QString ( "template/%1/source/%1/main.cpp" ).arg ( tempName ),
                        QString ( "%1/%2/source/%2/main.cpp" ).arg ( projDir ).arg ( className ), true );
    sf.copyFileToPath ( QString ( "template/%1/source/%1/mainwindow.cpp" ).arg ( tempName ),
                        QString ( "%1/%2/source/%2/mainwindow.cpp" ).arg ( projDir ).arg ( className ), true );
    sf.copyFileToPath ( QString ( "template/%1/source/%1/mainwindow.h" ).arg ( tempName ),
                        QString ( "%1/%2/source/%2/mainwindow.h" ).arg ( projDir ).arg ( className ), true );
    sf.copyFileToPath ( QString ( "template/%1/source/%1/mainwindow.ui" ).arg ( tempName ),
                        QString ( "%1/%2/source/%2/mainwindow.ui" ).arg ( projDir ).arg ( className ), true );

    //创建目标文件 这一步可以省略，在下边做。

    //把模板文件里的 关键字符串 进行合理更新，保存到目标文件
    ui->tx1->append ( "正在生成新工程文件。。。" );
    QByteArray bKey = className.toUpper().toLocal8Bit();
    QByteArray cKey = className.toLocal8Bit();
    QByteArray lKey = className.toLower().toLocal8Bit();

    QByteArray sBytes;
    QByteArray tBytes;

    QString sFile = QString ( "template/%1/%1.pro" ).arg ( tempName );
    QString tFile = QString ( "%1/%2/%2.pro" ).arg ( projDir ).arg ( className );
    ui->tx1->append ( tFile );

    QFile f0 ( sFile );
    f0.open ( QFile::ReadOnly );
    sBytes = f0.readAll();
    f0.close();
    tBytes = sBytes;
    tBytes = tBytes.replace ( tempName, cKey );
    tBytes = tBytes.replace ( tempName.toUpper(), bKey );
    tBytes = tBytes.replace ( tempName.toLower(), lKey );
    QFile f1 ( tFile );
    f1.open ( QFile::Truncate | QFile::WriteOnly );
    f1.write ( tBytes );
    f1.close();

    sFile = QString ( "template/%1/source/%1.pro" ).arg ( tempName );
    tFile = QString ( "%1/%2/source/%2.pro" ).arg ( projDir ).arg ( className );
    ui->tx1->append ( tFile );
    f0.setFileName ( sFile );
    f0.open ( QFile::ReadOnly );
    sBytes = f0.readAll();
    f0.close();
    tBytes = sBytes;
    tBytes = tBytes.replace ( tempName, cKey );
    tBytes = tBytes.replace ( tempName.toUpper(), bKey );
    tBytes = tBytes.replace ( tempName.toLower(), lKey );
    f1.setFileName ( tFile );
    f1.open ( QFile::Truncate | QFile::WriteOnly );
    f1.write ( tBytes );
    f1.close();

    //可替代
    sFile = QString ( "template/%1/source/%1/%1.pro" ).arg ( tempName );
    tFile = QString ( "%1/%2/source/%2/%2.pro" ).arg ( projDir ).arg ( className );
    ui->tx1->append ( tFile );
    f0.setFileName ( sFile );
    f0.open ( QFile::ReadOnly );
    sBytes = f0.readAll();
    f0.close();
    tBytes = sBytes;
    tBytes = tBytes.replace ( tempName, cKey );
    tBytes = tBytes.replace ( tempName.toUpper(), bKey );
    tBytes = tBytes.replace ( tempName.toLower(), lKey );
    f1.setFileName ( tFile );
    f1.open ( QFile::Truncate | QFile::WriteOnly );
    f1.write ( tBytes );
    f1.close();

    //可替代
    sFile = QString ( "template/%1/source/%1/mainwindow.ui" ).arg ( tempName );
    tFile = QString ( "%1/%2/source/%2/mainwindow.ui" ).arg ( projDir ).arg ( className );
    ui->tx1->append ( tFile );
    f0.setFileName ( sFile );
    f0.open ( QFile::ReadOnly );
    sBytes = f0.readAll();
    f0.close();
    tBytes = sBytes;
    tBytes = tBytes.replace ( tempName, cKey );
    tBytes = tBytes.replace ( tempName.toUpper(), bKey );
    tBytes = tBytes.replace ( tempName.toLower(), lKey );
    f1.setFileName ( tFile );
    f1.open ( QFile::Truncate | QFile::WriteOnly );
    f1.write ( tBytes );
    f1.close();

    sFile = QString ( "template/%1/source/%1/android/AndroidManifest.xml" ).arg ( tempName );
    tFile = QString ( "%1/%2/source/%2/android/AndroidManifest.xml" ).arg ( projDir ).arg ( className );
    ui->tx1->append ( tFile );
    f0.setFileName ( sFile );
    f0.open ( QFile::ReadOnly );
    sBytes = f0.readAll();
    f0.close();
    tBytes = sBytes;
    tBytes = tBytes.replace ( tempName, cKey );
    tBytes = tBytes.replace ( tempName.toUpper(), bKey );
    tBytes = tBytes.replace ( tempName.toLower(), lKey );
    f1.setFileName ( tFile );
    f1.open ( QFile::Truncate | QFile::WriteOnly );
    f1.write ( tBytes );
    f1.close();

    //这个循环完全可以替代上边的一些代码
    QDir d ( rootPath );
    d.cd ( QString ( "template/%1/source/%1" ).arg ( tempName ) );
#if 0
    foreach ( QFileInfo fi, d.entryInfoList() )
    {
        if ( !fi.isFile() )
            continue;

        sFile = QString ( "template/%1/source/%1/%2" ).arg ( tempName ).arg ( fi.fileName() );
        //必须按照相应大小写改变，保持风格。
        tFile = QString ( "%1/%2/source/%2/%3" ).arg ( projDir ).arg ( className )
                .arg ( fi.fileName().replace ( tempName, cKey )
                       .replace ( tempName.toUpper(), bKey ).replace ( tempName.toLower(), lKey ) );
        ui->tx1->append ( tFile );
        f0.setFileName ( sFile );
        f0.open ( QFile::ReadOnly );
        sBytes = f0.readAll();
        f0.close();
        tBytes = sBytes;
        tBytes = tBytes.replace ( tempName, cKey );
        tBytes = tBytes.replace ( tempName.toUpper(), bKey );
        tBytes = tBytes.replace ( tempName.toLower(), lKey );
        f1.setFileName ( tFile );
        f1.open ( QFile::Truncate | QFile::WriteOnly );
        f1.write ( tBytes );
        f1.close();
    }
#endif

    //写入列表内子工程的文件 这个地方 我用了面向对象思想 树对象，可是觉得笨。。。
    //现在的方法，保持了上边这个原始工程的完整性。
    for ( int i = 0; i < ui->listWidget->count(); i++ )
    {
        //把上边的过程走一遍

        //虽然有相对频繁文件操作，但是代码可读性好。
        QString subProjName = ui->listWidget->item ( i )->text();

        //创建列表子工程目录
        root.mkdir ( QString ( "source/%1" ).arg ( subProjName ) );

        //开始生成工程文件

        //+sub project。
        QString tFile = QString ( "%1/%2/source/%2.pro" ).arg ( projDir ).arg ( className );
        //QString importProFile = tFile;
        ui->tx1->append ( tFile );
        f1.setFileName ( tFile );
        //如果文件不存在，那么主要子工程，挂了。
        f1.open ( QFile::Append );
        tBytes = "";
        tBytes << QString ( "SUBDIRS += %1\n" ).arg ( subProjName ).toLocal8Bit();
        f1.write ( tBytes );
        f1.close();

        //开始生成具体的工程文件。
        //android直接拷贝 后续还有AndroidManifest.xml fixer
        ui->tx1->append ( "正在拷贝android文件夹。。。" );
        sf.copyDirectoryFiles ( QString ( "template/%1/source/%1/android" ).arg ( tempName ),
                                QString ( "%1/%2/source/%3/android" ).arg ( projDir ).arg ( className ).arg ( subProjName ), true );

        //AppRoot直接拷贝
        ui->tx1->append ( "正在拷贝AppRoot文件夹。。。" );
        sf.copyDirectoryFiles ( QString ( "template/%1/source/%1/AppRoot" ).arg ( tempName ),
                                QString ( "%1/%2/source/%3/AppRoot" ).arg ( projDir ).arg ( className ).arg ( subProjName ), true );

        QByteArray subbKey = subProjName.toUpper().toLocal8Bit();
        QByteArray subcKey = subProjName.toLocal8Bit();
        QByteArray sublKey = subProjName.toLower().toLocal8Bit();

        sFile = QString ( "template/%1/source/%1/android/AndroidManifest.xml" ).arg ( tempName );
        tFile = QString ( "%1/%2/source/%3/android/AndroidManifest.xml" ).arg ( projDir ).arg ( className ).arg ( subProjName );
        ui->tx1->append ( tFile );
        f0.setFileName ( sFile );
        f0.open ( QFile::ReadOnly );
        sBytes = f0.readAll();
        f0.close();
        tBytes = sBytes;
        tBytes = tBytes.replace ( tempName, subcKey );
        tBytes = tBytes.replace ( tempName.toUpper(), subbKey );
        tBytes = tBytes.replace ( tempName.toLower(), sublKey );
        f1.setFileName ( tFile );
        f1.open ( QFile::Truncate | QFile::WriteOnly );
        f1.write ( tBytes );
        f1.close();

        foreach ( QFileInfo fi, d.entryInfoList() )
        {
            if ( !fi.isFile() )
                continue;
            sFile = QString ( "template/%1/source/%1/%2" ).arg ( tempName ).arg ( fi.fileName() );
            //必须按照相应大小写改变，保持风格。
            tFile = QString ( "%1/%2/source/%3/%4" ).arg ( projDir ).arg ( className ).arg ( subProjName )
                    .arg ( fi.fileName().replace ( tempName, subcKey )
                           .replace ( tempName.toUpper(), subbKey ).replace ( tempName.toLower(), sublKey ) );
            ui->tx1->append ( tFile );
            f0.setFileName ( sFile );
            f0.open ( QFile::ReadOnly );
            sBytes = f0.readAll();
            f0.close();
            tBytes = sBytes;
            tBytes = tBytes.replace ( tempName, subcKey );
            tBytes = tBytes.replace ( tempName.toUpper(), subbKey );
            tBytes = tBytes.replace ( tempName.toLower(), sublKey );
            f1.setFileName ( tFile );
            f1.open ( QFile::Truncate | QFile::WriteOnly );
            f1.write ( tBytes );
            f1.close();
        }
    }

    //发布到Group
    if ( ui->checkBox->isChecked() )
    {
        for ( int i = 0; i < ui->listWidget->count(); i++ )
        {
            //.pro里add_setting_deploy(className)
            QString subProjName = ui->listWidget->item ( i )->text();

            QByteArray subbKey = subProjName.toUpper().toLocal8Bit();
            QByteArray subcKey = subProjName.toLocal8Bit();
            QByteArray sublKey = subProjName.toLower().toLocal8Bit();

            sFile = QString ( "template/%1/source/%1/%1.pro" ).arg ( tempName );
            tFile = QString ( "%1/%2/source/%3/%3.pro" ).arg ( projDir ).arg ( className ).arg ( subProjName );

            ui->tx1->append ( "updating " + tFile );
            f0.setFileName ( sFile );
            f0.open ( QFile::ReadOnly );
            sBytes = f0.readAll();
            f0.close();
            tBytes = sBytes;
            tBytes = tBytes.replace ( tempName, subcKey );
            tBytes = tBytes.replace ( tempName.toUpper(), subbKey );
            tBytes = tBytes.replace ( tempName.toLower(), sublKey );
            tBytes = tBytes.replace ( "add_deploy()",
                                      QString ( "add_setting_deploy(%1)\nadd_deploy()" ).arg ( className ).toLocal8Bit() );
            f1.setFileName ( tFile );
            f1.open ( QFile::Truncate | QFile::WriteOnly );
            f1.write ( tBytes );
            f1.close();
        }
    }

    ui->statusBar->showMessage ( "Sucess.", 2200 );
}

bool MainWindow::eventFilter ( QObject* watched, QEvent* event )
{
    if ( event->type() == QEvent::Paint )
        return QMainWindow::eventFilter ( watched, event );

    //if ( watched != ui->lineEdit)
    //return QMainWindow::eventFilter ( watched, event );

    if ( watched == ui->lineEdit )
    {
        if ( event->type() == QEvent::KeyRelease )
        {
            QKeyEvent* e = ( QKeyEvent* ) event;

            switch ( e->key() )
            {
                case Qt::Key_Enter:
                case Qt::Key_Return:
                {
                    emit clickBtn();
                    e->accept();
                    return true;
                }
                break;
                default:
                    break;
            }
        }
    }

    else if ( watched == ui->lineEdit_2 )
    {
        if ( event->type() == QEvent::KeyRelease )
        {
            QKeyEvent* e = ( QKeyEvent* ) event;

            switch ( e->key() )
            {
                case Qt::Key_Enter:
                case Qt::Key_Return:
                {
                    emit clickBtn2();
                    e->accept();
                    return true;
                }
                break;
                default:
                    break;
            }
        }
    }

    return QMainWindow::eventFilter ( watched, event );
}

void MainWindow::on_pushButton_2_clicked()
{
    if ( ui->lineEdit_2->text().isEmpty() )
        return;

    for ( int i = 0; i < ui->listWidget->count(); i++ )
    {
        QString subProjName = ui->listWidget->item ( i )->text();
        if ( subProjName == ui->lineEdit_2->text() )
            return;
    }

    if ( ui->lineEdit->text() == ui->lineEdit_2->text() )
        return;

    ui->listWidget->addItem ( ui->lineEdit_2->text() );
}

void MainWindow::on_pushButton_3_clicked()
{
    if ( ui->listWidget->count() <= 0 )
        return;

    QListWidgetItem* item = ui->listWidget->takeItem ( ui->listWidget->currentRow() );
    ui->listWidget->removeItemWidget ( item );
    //帮助文档说，用户需要手动删除item句柄。Qt不管理这个item的删除。
    delete item;
}
